@c4a/context-cli 0.7.30 → 0.7.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +300 -258
- package/indexers/contracts/profile-contract.json +245 -245
- package/indexers/release-manifest.json +1 -1
- package/package.json +12 -12
- package/plugins/VERSION +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/context-inspect-search.md +18 -0
- package/plugins/claude/skills/context-inspect-search/SKILL.md +18 -0
- package/plugins/codex/.codex-plugin/plugin.json +2 -2
- package/plugins/codex/skills/context-inspect-search/SKILL.md +18 -0
- package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor/commands/c4a-context-inspect-search.md +18 -0
- package/plugins/cursor/skills/context-inspect-search/SKILL.md +18 -0
- package/plugins/skills/context-inspect-search/SKILL.md +18 -0
- package/providers/context/manifest.json +7 -7
- package/providers/context/provider.yaml +1 -1
- package/providers/context/resources/manuals/guides/lark-resources.md +22 -10
- package/providers/context/resources/procedures/document-capture.md +17 -10
package/cli.js
CHANGED
|
@@ -42637,7 +42637,7 @@ function parseDocumentResourceMaterialization(value, field) {
|
|
|
42637
42637
|
...reason !== undefined ? { reason } : {}
|
|
42638
42638
|
};
|
|
42639
42639
|
});
|
|
42640
|
-
const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
|
|
42640
|
+
const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
|
|
42641
42641
|
if (value.status !== expectedStatus)
|
|
42642
42642
|
throw new TypeError(`${field}.status must be ${expectedStatus} for its items`);
|
|
42643
42643
|
const expected = (status) => {
|
|
@@ -90705,7 +90705,7 @@ function documentSnapshotFidelityState(manifest, captureReport) {
|
|
|
90705
90705
|
],
|
|
90706
90706
|
warnings: [
|
|
90707
90707
|
...report === undefined ? [] : render((issue) => issue.impact === "projection" || issue.severity === "warning"),
|
|
90708
|
-
...(resources?.items ?? []).filter((item) => item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
|
|
90708
|
+
...(resources?.items ?? []).filter((item) => item.reason_code === "document.resource.preview" || item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
|
|
90709
90709
|
]
|
|
90710
90710
|
};
|
|
90711
90711
|
}
|
|
@@ -97826,32 +97826,6 @@ var init_larkDocxXml = __esm(() => {
|
|
|
97826
97826
|
]);
|
|
97827
97827
|
});
|
|
97828
97828
|
|
|
97829
|
-
// src/lib/larkImagePolicy.ts
|
|
97830
|
-
function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
|
|
97831
|
-
if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
|
|
97832
|
-
return false;
|
|
97833
|
-
const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
|
|
97834
|
-
if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
|
|
97835
|
-
return false;
|
|
97836
|
-
const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
|
|
97837
|
-
replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
|
|
97838
|
-
items.push({
|
|
97839
|
-
kind: resource.kind,
|
|
97840
|
-
locator: resource.locator,
|
|
97841
|
-
status: "reference-only",
|
|
97842
|
-
required: false,
|
|
97843
|
-
asset_paths: [],
|
|
97844
|
-
reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
|
|
97845
|
-
reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
|
|
97846
|
-
});
|
|
97847
|
-
return true;
|
|
97848
|
-
}
|
|
97849
|
-
var LarkResourceBudgetError;
|
|
97850
|
-
var init_larkImagePolicy = __esm(() => {
|
|
97851
|
-
LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
|
|
97852
|
-
};
|
|
97853
|
-
});
|
|
97854
|
-
|
|
97855
97829
|
// src/lib/larkResourceCommand.ts
|
|
97856
97830
|
function stableJson(value) {
|
|
97857
97831
|
if (value === undefined)
|
|
@@ -97880,13 +97854,13 @@ function commandError(fallback, detail) {
|
|
|
97880
97854
|
if (detail === undefined)
|
|
97881
97855
|
return new LarkResourceCommandError(fallback);
|
|
97882
97856
|
const message = [detail.message, detail.hint, detail.code].filter((value) => typeof value === "string" || typeof value === "number").map(String).join("; ");
|
|
97883
|
-
return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined);
|
|
97857
|
+
return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined, typeof detail.code === "string" || typeof detail.code === "number" ? detail.code : undefined, typeof detail.log_id === "string" ? detail.log_id : undefined);
|
|
97884
97858
|
}
|
|
97885
97859
|
async function runLarkResourceCommand(runner2, args, options) {
|
|
97886
97860
|
const result = await runner2(args, options);
|
|
97887
97861
|
if (result.exitCode !== 0) {
|
|
97888
97862
|
const fallback = result.stderr.trim() || `lark-cli ${args.slice(0, 2).join(" ")} failed with exit code ${result.exitCode ?? "unknown"}`;
|
|
97889
|
-
throw commandError(fallback, errorDetail(result.stderr));
|
|
97863
|
+
throw commandError(fallback, errorDetail(result.stderr) ?? errorDetail(result.stdout));
|
|
97890
97864
|
}
|
|
97891
97865
|
const trimmed = result.stdout.trim();
|
|
97892
97866
|
if (!trimmed.startsWith("{"))
|
|
@@ -97906,24 +97880,78 @@ async function runLarkResourceCommand(runner2, args, options) {
|
|
|
97906
97880
|
}
|
|
97907
97881
|
return result.stdout;
|
|
97908
97882
|
}
|
|
97883
|
+
function isLarkResourcePermissionDenied(error) {
|
|
97884
|
+
return error instanceof LarkResourceCommandError && (String(error.code) === "403" || error.errorType === "authorization" && ["permission_denied", "access_denied", "missing_scope"].includes(error.errorSubtype ?? ""));
|
|
97885
|
+
}
|
|
97909
97886
|
var LarkResourceCommandError;
|
|
97910
97887
|
var init_larkResourceCommand = __esm(() => {
|
|
97911
97888
|
LarkResourceCommandError = class LarkResourceCommandError extends Error {
|
|
97912
97889
|
errorType;
|
|
97913
97890
|
errorSubtype;
|
|
97914
|
-
|
|
97891
|
+
code;
|
|
97892
|
+
logId;
|
|
97893
|
+
constructor(message, errorType, errorSubtype, code3, logId) {
|
|
97915
97894
|
super(message);
|
|
97916
97895
|
this.errorType = errorType;
|
|
97917
97896
|
this.errorSubtype = errorSubtype;
|
|
97897
|
+
this.code = code3;
|
|
97898
|
+
this.logId = logId;
|
|
97918
97899
|
this.name = "LarkResourceCommandError";
|
|
97919
97900
|
}
|
|
97920
97901
|
};
|
|
97921
97902
|
});
|
|
97922
97903
|
|
|
97904
|
+
// src/lib/larkMediaDownload.ts
|
|
97905
|
+
import { readdir as readdir21, rm as rm20 } from "node:fs/promises";
|
|
97906
|
+
import { join as join94 } from "node:path";
|
|
97907
|
+
async function downloadLarkMedia(input) {
|
|
97908
|
+
const shared = ["--as", input.identity, "--token", input.token, "--output", "./resource", "--format", "json"];
|
|
97909
|
+
try {
|
|
97910
|
+
await runLarkResourceCommand(input.runner, ["docs", "+media-download", ...shared, "--type", input.type, "--overwrite"], { cwd: input.cwd });
|
|
97911
|
+
return "original";
|
|
97912
|
+
} catch (error) {
|
|
97913
|
+
if (!input.allowPreview || !isLarkResourcePermissionDenied(error))
|
|
97914
|
+
throw error;
|
|
97915
|
+
for (const entry of await readdir21(input.cwd))
|
|
97916
|
+
await rm20(join94(input.cwd, entry), { recursive: true, force: true });
|
|
97917
|
+
await runLarkResourceCommand(input.runner, ["docs", "+media-preview", ...shared], { cwd: input.cwd });
|
|
97918
|
+
return "preview";
|
|
97919
|
+
}
|
|
97920
|
+
}
|
|
97921
|
+
var init_larkMediaDownload = __esm(() => {
|
|
97922
|
+
init_larkResourceCommand();
|
|
97923
|
+
});
|
|
97924
|
+
|
|
97925
|
+
// src/lib/larkImagePolicy.ts
|
|
97926
|
+
function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
|
|
97927
|
+
if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
|
|
97928
|
+
return false;
|
|
97929
|
+
const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
|
|
97930
|
+
if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
|
|
97931
|
+
return false;
|
|
97932
|
+
const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
|
|
97933
|
+
replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
|
|
97934
|
+
items.push({
|
|
97935
|
+
kind: resource.kind,
|
|
97936
|
+
locator: resource.locator,
|
|
97937
|
+
status: "reference-only",
|
|
97938
|
+
required: false,
|
|
97939
|
+
asset_paths: [],
|
|
97940
|
+
reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
|
|
97941
|
+
reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
|
|
97942
|
+
});
|
|
97943
|
+
return true;
|
|
97944
|
+
}
|
|
97945
|
+
var LarkResourceBudgetError;
|
|
97946
|
+
var init_larkImagePolicy = __esm(() => {
|
|
97947
|
+
LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
|
|
97948
|
+
};
|
|
97949
|
+
});
|
|
97950
|
+
|
|
97923
97951
|
// src/lib/larkResourceMaterialization.ts
|
|
97924
97952
|
import { createHash as createHash28 } from "node:crypto";
|
|
97925
|
-
import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as
|
|
97926
|
-
import { extname as extname13, join as
|
|
97953
|
+
import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir22, rm as rm21 } from "node:fs/promises";
|
|
97954
|
+
import { extname as extname13, join as join95 } from "node:path";
|
|
97927
97955
|
import { tmpdir } from "node:os";
|
|
97928
97956
|
function countByKind(items, status) {
|
|
97929
97957
|
const counts2 = new Map;
|
|
@@ -98029,33 +98057,19 @@ function findBooleanField(value, name3) {
|
|
|
98029
98057
|
async function downloadedFile(input) {
|
|
98030
98058
|
if (input.localPath !== undefined) {
|
|
98031
98059
|
const bytes = await readFile74(input.localPath);
|
|
98032
|
-
return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes) };
|
|
98060
|
+
return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes), representation: "original" };
|
|
98033
98061
|
}
|
|
98034
|
-
const tempRoot = await mkdtemp4(
|
|
98062
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-resource-"));
|
|
98035
98063
|
try {
|
|
98036
|
-
await
|
|
98037
|
-
|
|
98038
|
-
"+media-download",
|
|
98039
|
-
"--as",
|
|
98040
|
-
input.identity,
|
|
98041
|
-
"--token",
|
|
98042
|
-
input.token,
|
|
98043
|
-
"--type",
|
|
98044
|
-
input.type,
|
|
98045
|
-
"--output",
|
|
98046
|
-
"./resource",
|
|
98047
|
-
"--overwrite",
|
|
98048
|
-
"--format",
|
|
98049
|
-
"json"
|
|
98050
|
-
], { cwd: tempRoot });
|
|
98051
|
-
const entries2 = (await readdir21(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
|
|
98064
|
+
const representation = await downloadLarkMedia({ ...input, cwd: tempRoot });
|
|
98065
|
+
const entries2 = (await readdir22(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
|
|
98052
98066
|
if (entries2.length !== 1)
|
|
98053
98067
|
throw new Error(`media download produced ${entries2.length} files, expected exactly one`);
|
|
98054
98068
|
const path3 = entries2[0]?.name ?? "resource.bin";
|
|
98055
|
-
const bytes = await readFile74(
|
|
98056
|
-
return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
|
|
98069
|
+
const bytes = await readFile74(join95(tempRoot, path3));
|
|
98070
|
+
return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes), representation };
|
|
98057
98071
|
} finally {
|
|
98058
|
-
await
|
|
98072
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98059
98073
|
}
|
|
98060
98074
|
}
|
|
98061
98075
|
function parseCsv(value) {
|
|
@@ -98143,9 +98157,9 @@ async function sheetMaterialization(resource, runner2, identity2) {
|
|
|
98143
98157
|
const sheetId = resource.attributes["sheet-id"];
|
|
98144
98158
|
if (token === undefined || sheetId === undefined)
|
|
98145
98159
|
throw new Error("embedded Sheet requires token and sheet-id");
|
|
98146
|
-
const tempRoot = await mkdtemp4(
|
|
98160
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-sheet-"));
|
|
98147
98161
|
try {
|
|
98148
|
-
const outputPath =
|
|
98162
|
+
const outputPath = join95(tempRoot, "sheet.json");
|
|
98149
98163
|
const stdout = await runLarkResourceCommand(runner2, [
|
|
98150
98164
|
"sheets",
|
|
98151
98165
|
"+csv-get",
|
|
@@ -98187,7 +98201,7 @@ ${markdownTable2(parseCsv(csv))}
|
|
|
98187
98201
|
[CSV snapshot](${sourceAssetTarget(path3)}) <!-- ${resource.locator} -->`
|
|
98188
98202
|
};
|
|
98189
98203
|
} finally {
|
|
98190
|
-
await
|
|
98204
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98191
98205
|
}
|
|
98192
98206
|
}
|
|
98193
98207
|
function basePageRecords(value) {
|
|
@@ -98301,7 +98315,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98301
98315
|
if (token === undefined)
|
|
98302
98316
|
throw new Error(`${resource.kind} has no whiteboard token`);
|
|
98303
98317
|
const preview = await downloadedFile({ runner: runner2, identity: identity2, token, type: "whiteboard" });
|
|
98304
|
-
const tempRoot = await mkdtemp4(
|
|
98318
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-whiteboard-"));
|
|
98305
98319
|
let rawPayload;
|
|
98306
98320
|
try {
|
|
98307
98321
|
await runLarkResourceCommand(runner2, [
|
|
@@ -98319,9 +98333,9 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98319
98333
|
"--format",
|
|
98320
98334
|
"json"
|
|
98321
98335
|
], { cwd: tempRoot });
|
|
98322
|
-
rawPayload = JSON.parse(await readFile74(
|
|
98336
|
+
rawPayload = JSON.parse(await readFile74(join95(tempRoot, "raw.json"), "utf8"));
|
|
98323
98337
|
} finally {
|
|
98324
|
-
await
|
|
98338
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98325
98339
|
}
|
|
98326
98340
|
const digest6 = resourceDigest(resource);
|
|
98327
98341
|
const previewPath = `materialized/${resource.kind}/${digest6}${extensionFor2(preview.mediaType, preview.path)}`;
|
|
@@ -98380,7 +98394,7 @@ function referenceOnlyReason(resource) {
|
|
|
98380
98394
|
}
|
|
98381
98395
|
function materializationReport(items) {
|
|
98382
98396
|
const hasRequiredFailure = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code));
|
|
98383
|
-
const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
|
|
98397
|
+
const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
|
|
98384
98398
|
return {
|
|
98385
98399
|
status: hasRequiredFailure ? "error" : hasOptionalFailure ? "warning" : "complete",
|
|
98386
98400
|
discovered: countByKind(items),
|
|
@@ -98391,7 +98405,7 @@ function materializationReport(items) {
|
|
|
98391
98405
|
};
|
|
98392
98406
|
}
|
|
98393
98407
|
function resourceFailureReasonCode(resource, error) {
|
|
98394
|
-
if (error
|
|
98408
|
+
if (isLarkResourcePermissionDenied(error)) {
|
|
98395
98409
|
return DOCUMENT_RESOURCE_PERMISSION_DENIED_REASON_CODE;
|
|
98396
98410
|
}
|
|
98397
98411
|
if (resource.kind !== "diagram" && resource.kind !== "whiteboard")
|
|
@@ -98511,6 +98525,7 @@ async function materializeLarkResources(input) {
|
|
|
98511
98525
|
identity: identity2,
|
|
98512
98526
|
token,
|
|
98513
98527
|
type: "media",
|
|
98528
|
+
allowPreview: resource.kind === "image",
|
|
98514
98529
|
...input.mediaFiles?.[token] === undefined ? {} : { localPath: input.mediaFiles[token] }
|
|
98515
98530
|
});
|
|
98516
98531
|
if (omitLarkImage(resource, input.policy, items, replacements, downloaded.mediaType))
|
|
@@ -98522,7 +98537,7 @@ async function materializeLarkResources(input) {
|
|
|
98522
98537
|
bytes: downloaded.bytes,
|
|
98523
98538
|
mediaType: downloaded.mediaType,
|
|
98524
98539
|
role: "evidence",
|
|
98525
|
-
source: { kind: resource.kind, locator: resource.locator }
|
|
98540
|
+
source: { kind: resource.kind, locator: resource.locator, identity: identity2, representation: downloaded.representation }
|
|
98526
98541
|
};
|
|
98527
98542
|
assertBudget(asset, input.policy, totalBytes);
|
|
98528
98543
|
totalBytes += asset.bytes.byteLength;
|
|
@@ -98530,8 +98545,17 @@ async function materializeLarkResources(input) {
|
|
|
98530
98545
|
const title2 = markdownLabel(safeLabel(resource.title, resource.kind));
|
|
98531
98546
|
const target = sourceAssetTarget(asset.path);
|
|
98532
98547
|
const replacement = downloaded.mediaType.startsWith("image/") ? ` <!-- ${resource.locator} -->` : `[${title2}](${target}) <!-- ${resource.locator} -->`;
|
|
98533
|
-
replacements.set(resource.locator, replacement
|
|
98534
|
-
|
|
98548
|
+
replacements.set(resource.locator, downloaded.representation === "preview" ? `${replacement}
|
|
98549
|
+
|
|
98550
|
+
> Image preview captured; the original could not be downloaded.` : replacement);
|
|
98551
|
+
items.push({
|
|
98552
|
+
kind: resource.kind,
|
|
98553
|
+
locator: resource.locator,
|
|
98554
|
+
status: "materialized",
|
|
98555
|
+
required,
|
|
98556
|
+
asset_paths: [asset.path],
|
|
98557
|
+
...downloaded.representation === "preview" ? { reason_code: "document.resource.preview", reason: "Same-identity preview captured; original download permission denied" } : {}
|
|
98558
|
+
});
|
|
98535
98559
|
} catch (error) {
|
|
98536
98560
|
if (error instanceof LarkResourceBudgetError && omitLarkImage(resource, input.policy, items, replacements, undefined, error.message))
|
|
98537
98561
|
return;
|
|
@@ -98579,6 +98603,7 @@ function applyLarkResourceReplacements(markdown, resources, replacements) {
|
|
|
98579
98603
|
}
|
|
98580
98604
|
var REQUIRED_KINDS, MEDIA_TYPES_BY_EXTENSION;
|
|
98581
98605
|
var init_larkResourceMaterialization = __esm(() => {
|
|
98606
|
+
init_larkMediaDownload();
|
|
98582
98607
|
init_larkImagePolicy();
|
|
98583
98608
|
init_src3();
|
|
98584
98609
|
init_larkResourceCommand();
|
|
@@ -98691,10 +98716,13 @@ function credentialFailure(result) {
|
|
|
98691
98716
|
function createLarkReadSession(runner2, initial, fallback = initial === "bot") {
|
|
98692
98717
|
let identity2 = initial;
|
|
98693
98718
|
let usedFallback = false;
|
|
98719
|
+
let readingDocument = false;
|
|
98720
|
+
let locked = false;
|
|
98721
|
+
const restart = new Error("Restart document with user identity");
|
|
98694
98722
|
const run = async (args, options) => {
|
|
98695
98723
|
const explicit = args.indexOf("--as");
|
|
98696
98724
|
const requested = explicit >= 0 ? args[explicit + 1] : identity2;
|
|
98697
|
-
const selected = usedFallback ?
|
|
98725
|
+
const selected = locked || usedFallback ? identity2 : requested === "bot" ? "bot" : "user";
|
|
98698
98726
|
const withIdentity = [...args];
|
|
98699
98727
|
if (explicit >= 0)
|
|
98700
98728
|
withIdentity[explicit + 1] = selected;
|
|
@@ -98702,14 +98730,28 @@ function createLarkReadSession(runner2, initial, fallback = initial === "bot") {
|
|
|
98702
98730
|
withIdentity.push("--as", selected);
|
|
98703
98731
|
const result = await runner2(withIdentity, options);
|
|
98704
98732
|
identity2 = selected;
|
|
98705
|
-
if (identity2
|
|
98706
|
-
|
|
98707
|
-
|
|
98708
|
-
identity2 = "user";
|
|
98709
|
-
withIdentity[withIdentity.indexOf("--as") + 1] = "user";
|
|
98710
|
-
return runner2(withIdentity, options);
|
|
98733
|
+
if (readingDocument && identity2 === "bot" && fallback && !usedFallback && !args.includes("--help") && credentialFailure(result))
|
|
98734
|
+
throw restart;
|
|
98735
|
+
return result;
|
|
98711
98736
|
};
|
|
98712
|
-
|
|
98737
|
+
async function readDocument(read) {
|
|
98738
|
+
readingDocument = true;
|
|
98739
|
+
try {
|
|
98740
|
+
try {
|
|
98741
|
+
return await read();
|
|
98742
|
+
} catch (error) {
|
|
98743
|
+
if (error !== restart)
|
|
98744
|
+
throw error;
|
|
98745
|
+
usedFallback = true;
|
|
98746
|
+
identity2 = "user";
|
|
98747
|
+
return await read();
|
|
98748
|
+
}
|
|
98749
|
+
} finally {
|
|
98750
|
+
readingDocument = false;
|
|
98751
|
+
locked = true;
|
|
98752
|
+
}
|
|
98753
|
+
}
|
|
98754
|
+
return { run, readDocument, get identity() {
|
|
98713
98755
|
return identity2;
|
|
98714
98756
|
}, get usedFallback() {
|
|
98715
98757
|
return usedFallback;
|
|
@@ -99054,7 +99096,7 @@ async function fetchFeishuDocSnapshot(input, runner2 = defaultRunner) {
|
|
|
99054
99096
|
fetched: await fetchDocsResponse(input, docsFetchPlan, runner2, input.prefetched.identity),
|
|
99055
99097
|
identity: input.prefetched.identity,
|
|
99056
99098
|
fallback: false
|
|
99057
|
-
} : await fetchWithIdentity({ ...input, identity: preference }, docsFetchPlan, runner2);
|
|
99099
|
+
} : await session.readDocument(() => fetchWithIdentity({ ...input, identity: preference }, docsFetchPlan, runner2));
|
|
99058
99100
|
let fetched = identityFetch.fetched;
|
|
99059
99101
|
let accessIdentity = input.prefetched?.identity ?? session.identity;
|
|
99060
99102
|
let projection;
|
|
@@ -99245,8 +99287,8 @@ var init_sensitiveSourceLiteral = __esm(() => {
|
|
|
99245
99287
|
});
|
|
99246
99288
|
|
|
99247
99289
|
// src/project/documentCaptureLark.ts
|
|
99248
|
-
import { readdir as
|
|
99249
|
-
import { basename as basename10, extname as extname14, join as
|
|
99290
|
+
import { readdir as readdir23, readFile as readFile75 } from "node:fs/promises";
|
|
99291
|
+
import { basename as basename10, extname as extname14, join as join96 } from "node:path";
|
|
99250
99292
|
function titleFromMarkdown2(markdown, fallbackPath) {
|
|
99251
99293
|
const heading2 = markdown.split(`
|
|
99252
99294
|
`).find((line) => /^#\s+\S/u.test(line));
|
|
@@ -99273,7 +99315,7 @@ async function fileContentMatches(path3, content3) {
|
|
|
99273
99315
|
}
|
|
99274
99316
|
}
|
|
99275
99317
|
function sourceManifestPath2(entry) {
|
|
99276
|
-
return entry.snapshot?.manifest ??
|
|
99318
|
+
return entry.snapshot?.manifest ?? join96(entry.materializedAt, "manifest.json");
|
|
99277
99319
|
}
|
|
99278
99320
|
function larkRuntimeError(message, detail) {
|
|
99279
99321
|
return new ContextError(ExitCode.ExternalToolError, message, {
|
|
@@ -99400,12 +99442,12 @@ function assetManifestEntry(asset, assetRoot) {
|
|
|
99400
99442
|
};
|
|
99401
99443
|
}
|
|
99402
99444
|
async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
99403
|
-
const assetsRoot =
|
|
99445
|
+
const assetsRoot = join96(root2, assetRoot);
|
|
99404
99446
|
const files = [];
|
|
99405
99447
|
const visit4 = async (dir, prefix = assetRoot) => {
|
|
99406
99448
|
let entries2;
|
|
99407
99449
|
try {
|
|
99408
|
-
entries2 = await
|
|
99450
|
+
entries2 = await readdir23(dir, { withFileTypes: true });
|
|
99409
99451
|
} catch (error) {
|
|
99410
99452
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
99411
99453
|
return;
|
|
@@ -99413,7 +99455,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99413
99455
|
}
|
|
99414
99456
|
for (const entry of entries2) {
|
|
99415
99457
|
const relPath = `${prefix}/${entry.name}`;
|
|
99416
|
-
const absolutePath =
|
|
99458
|
+
const absolutePath = join96(dir, entry.name);
|
|
99417
99459
|
if (entry.isDirectory()) {
|
|
99418
99460
|
await visit4(absolutePath, relPath);
|
|
99419
99461
|
continue;
|
|
@@ -99428,7 +99470,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99428
99470
|
}
|
|
99429
99471
|
async function staleSnapshotAssetPaths(input) {
|
|
99430
99472
|
const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
|
|
99431
|
-
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) =>
|
|
99473
|
+
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join96(input.materializedAtAbsPath, path3));
|
|
99432
99474
|
}
|
|
99433
99475
|
function normalizeLarkError(error, sourceName) {
|
|
99434
99476
|
if (error instanceof ContextError)
|
|
@@ -99542,9 +99584,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99542
99584
|
locator
|
|
99543
99585
|
}];
|
|
99544
99586
|
const manifestPath = sourceManifestPath2(entry);
|
|
99545
|
-
const manifestAbsPath =
|
|
99587
|
+
const manifestAbsPath = join96(input.projectRoot, manifestPath);
|
|
99546
99588
|
const materializedAt = entry.materializedAt;
|
|
99547
|
-
const materializedAtAbsPath =
|
|
99589
|
+
const materializedAtAbsPath = join96(input.projectRoot, materializedAt);
|
|
99548
99590
|
const manifest = createDocumentSnapshotManifest({
|
|
99549
99591
|
sourceType: "lark",
|
|
99550
99592
|
sourceName: resolved.sourceName,
|
|
@@ -99578,13 +99620,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99578
99620
|
}));
|
|
99579
99621
|
try {
|
|
99580
99622
|
const requestedWrites = [{
|
|
99581
|
-
path:
|
|
99623
|
+
path: join96(materializedAtAbsPath, documentPath),
|
|
99582
99624
|
bytes: normalized
|
|
99583
99625
|
}];
|
|
99584
99626
|
for (const asset of assets) {
|
|
99585
99627
|
if (asset.bytes !== undefined) {
|
|
99586
99628
|
requestedWrites.push({
|
|
99587
|
-
path:
|
|
99629
|
+
path: join96(materializedAtAbsPath, asset.entry.path),
|
|
99588
99630
|
bytes: asset.bytes
|
|
99589
99631
|
});
|
|
99590
99632
|
}
|
|
@@ -99601,7 +99643,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99601
99643
|
currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
|
|
99602
99644
|
});
|
|
99603
99645
|
await applyAtomicFileBatch({
|
|
99604
|
-
transactionRoot:
|
|
99646
|
+
transactionRoot: join96(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
|
|
99605
99647
|
writes,
|
|
99606
99648
|
removals
|
|
99607
99649
|
});
|
|
@@ -99747,7 +99789,7 @@ __export(exports_articleRetirement, {
|
|
|
99747
99789
|
retireArticles: () => retireArticles,
|
|
99748
99790
|
articleRetirementSchema: () => articleRetirementSchema
|
|
99749
99791
|
});
|
|
99750
|
-
import { readFile as readFile81, readdir as
|
|
99792
|
+
import { readFile as readFile81, readdir as readdir24 } from "node:fs/promises";
|
|
99751
99793
|
import { posix as posix10 } from "node:path";
|
|
99752
99794
|
function rebuildInput(revision) {
|
|
99753
99795
|
return JSON.stringify({ id: `retirement-${revision.slice(7)}`, operation: "rebuild", timing: "priority", targets: [] });
|
|
@@ -99880,7 +99922,7 @@ async function retireArticles(input) {
|
|
|
99880
99922
|
}
|
|
99881
99923
|
async function inspectTemplates(directory2) {
|
|
99882
99924
|
const absolute = await safeProjectTarget(input.projectRoot, directory2);
|
|
99883
|
-
const entries2 = await
|
|
99925
|
+
const entries2 = await readdir24(absolute, { withFileTypes: true }).catch((error) => {
|
|
99884
99926
|
if (error.code === "ENOENT")
|
|
99885
99927
|
return [];
|
|
99886
99928
|
throw error;
|
|
@@ -100030,8 +100072,8 @@ __export(exports_writeLockRecovery, {
|
|
|
100030
100072
|
recoverWriterLock: () => recoverWriterLock,
|
|
100031
100073
|
inspectWriterLock: () => inspectWriterLock
|
|
100032
100074
|
});
|
|
100033
|
-
import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as
|
|
100034
|
-
import { join as
|
|
100075
|
+
import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir25, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
|
|
100076
|
+
import { join as join101 } from "node:path";
|
|
100035
100077
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
|
|
100036
100078
|
async function inspectWriterLock(root2) {
|
|
100037
100079
|
const path3 = await safeProjectTarget(root2, lockRelative);
|
|
@@ -100078,19 +100120,19 @@ async function recoverWriterLock(input) {
|
|
|
100078
100120
|
};
|
|
100079
100121
|
if (input.plan_digest !== before.digest)
|
|
100080
100122
|
throw new Error("Writer lock changed; preview recovery again.");
|
|
100081
|
-
const path3 =
|
|
100082
|
-
const guard =
|
|
100123
|
+
const path3 = join101(input.projectRoot, lockRelative);
|
|
100124
|
+
const guard = join101(path3, ".recovery");
|
|
100083
100125
|
await mkdir34(guard);
|
|
100084
100126
|
let archived = false;
|
|
100085
100127
|
try {
|
|
100086
100128
|
const current2 = await inspectWriterLock(input.projectRoot);
|
|
100087
100129
|
if (current2?.digest !== before.digest || current2.process_state !== "not-running")
|
|
100088
100130
|
throw new Error("Writer lock changed or owner resumed; keep the lock.");
|
|
100089
|
-
const names = await
|
|
100131
|
+
const names = await readdir25(path3);
|
|
100090
100132
|
if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
|
|
100091
100133
|
throw new Error("Unexpected lock contents; preserve for diagnosis.");
|
|
100092
100134
|
const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
|
|
100093
|
-
await rename8(path3,
|
|
100135
|
+
await rename8(path3, join101(input.projectRoot, archive));
|
|
100094
100136
|
archived = true;
|
|
100095
100137
|
return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
|
|
100096
100138
|
} finally {
|
|
@@ -100114,8 +100156,8 @@ __export(exports_taskRecovery, {
|
|
|
100114
100156
|
RECOVERY_COMMAND: () => RECOVERY_COMMAND
|
|
100115
100157
|
});
|
|
100116
100158
|
import { existsSync as existsSync26 } from "node:fs";
|
|
100117
|
-
import { dirname as dirname41, join as
|
|
100118
|
-
import { lstat as lstat11, readdir as
|
|
100159
|
+
import { dirname as dirname41, join as join102 } from "node:path";
|
|
100160
|
+
import { lstat as lstat11, readdir as readdir26, readFile as readFile83 } from "node:fs/promises";
|
|
100119
100161
|
async function recoveryText(root2, path3) {
|
|
100120
100162
|
const target = await safeProjectTarget(root2, path3);
|
|
100121
100163
|
try {
|
|
@@ -100132,7 +100174,7 @@ async function recoveryJournals(root2) {
|
|
|
100132
100174
|
await safeProjectTarget(root2, path3);
|
|
100133
100175
|
let stat11;
|
|
100134
100176
|
try {
|
|
100135
|
-
stat11 = await lstat11(
|
|
100177
|
+
stat11 = await lstat11(join102(root2, path3));
|
|
100136
100178
|
} catch (error) {
|
|
100137
100179
|
if (error.code === "ENOENT")
|
|
100138
100180
|
return;
|
|
@@ -100143,7 +100185,7 @@ async function recoveryJournals(root2) {
|
|
|
100143
100185
|
if (stat11.isDirectory()) {
|
|
100144
100186
|
if (depth > 3)
|
|
100145
100187
|
throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
|
|
100146
|
-
for (const name3 of (await
|
|
100188
|
+
for (const name3 of (await readdir26(join102(root2, path3))).sort())
|
|
100147
100189
|
await visit4(`${path3}/${name3}`, depth + 1);
|
|
100148
100190
|
} else if (stat11.isFile())
|
|
100149
100191
|
entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
|
|
@@ -100155,8 +100197,8 @@ function recoveryResources() {
|
|
|
100155
100197
|
try {
|
|
100156
100198
|
const root2 = dirname41(contextWorkflowProviderPath());
|
|
100157
100199
|
const resources = {
|
|
100158
|
-
skill:
|
|
100159
|
-
issue_template:
|
|
100200
|
+
skill: join102(root2, "skills/recover-workspace/SKILL.md"),
|
|
100201
|
+
issue_template: join102(root2, "resources/templates/recovery-issue.md")
|
|
100160
100202
|
};
|
|
100161
100203
|
if (!Object.values(resources).every((path3) => existsSync26(path3)))
|
|
100162
100204
|
throw new Error("Recovery resources are absent from this Provider.");
|
|
@@ -100242,7 +100284,7 @@ __export(exports_taskLocalSourceAdjustment, {
|
|
|
100242
100284
|
adjustLocalRevisionSources: () => adjustLocalRevisionSources
|
|
100243
100285
|
});
|
|
100244
100286
|
import { readFile as readFile84 } from "node:fs/promises";
|
|
100245
|
-
import { join as
|
|
100287
|
+
import { join as join103 } from "node:path";
|
|
100246
100288
|
async function adjustLocalRevisionSources(root2, input) {
|
|
100247
100289
|
const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
|
|
100248
100290
|
if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
|
|
@@ -100285,7 +100327,7 @@ async function adjustLocalRevisionSources(root2, input) {
|
|
|
100285
100327
|
if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
|
|
100286
100328
|
throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
|
|
100287
100329
|
}
|
|
100288
|
-
const raw = await readFile84(
|
|
100330
|
+
const raw = await readFile84(join103(root2, await revisionStoragePath(root2)), "utf8");
|
|
100289
100331
|
let next2;
|
|
100290
100332
|
const discardIds = new Set;
|
|
100291
100333
|
if (!input.refresh) {
|
|
@@ -100388,7 +100430,7 @@ ${input.instruction}` : revision.instruction
|
|
|
100388
100430
|
content: content3
|
|
100389
100431
|
}];
|
|
100390
100432
|
if (discardIds.size > 0) {
|
|
100391
|
-
const ledger = await readFile84(
|
|
100433
|
+
const ledger = await readFile84(join103(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
|
|
100392
100434
|
if (error.code === "ENOENT")
|
|
100393
100435
|
return;
|
|
100394
100436
|
throw error;
|
|
@@ -100645,7 +100687,7 @@ __export(exports_managedDocumentRename, {
|
|
|
100645
100687
|
renameManagedDocument: () => renameManagedDocument
|
|
100646
100688
|
});
|
|
100647
100689
|
import { readFile as readFile92 } from "node:fs/promises";
|
|
100648
|
-
import { join as
|
|
100690
|
+
import { join as join111, posix as posix11 } from "node:path";
|
|
100649
100691
|
async function optionalText2(path3) {
|
|
100650
100692
|
try {
|
|
100651
100693
|
return await readFile92(path3, "utf8");
|
|
@@ -100732,7 +100774,7 @@ async function renameManagedDocument(input) {
|
|
|
100732
100774
|
if (path3.split("/").includes("..") || path3.startsWith("/"))
|
|
100733
100775
|
throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
|
|
100734
100776
|
await safeProjectTarget(input.projectRoot, path3);
|
|
100735
|
-
const before = await optionalText2(
|
|
100777
|
+
const before = await optionalText2(join111(input.projectRoot, path3));
|
|
100736
100778
|
if (before === undefined)
|
|
100737
100779
|
continue;
|
|
100738
100780
|
let after;
|
|
@@ -100821,7 +100863,7 @@ var init_managedDocumentRename = __esm(() => {
|
|
|
100821
100863
|
|
|
100822
100864
|
// src/cli.ts
|
|
100823
100865
|
import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
|
|
100824
|
-
import { dirname as dirname49, join as
|
|
100866
|
+
import { dirname as dirname49, join as join117 } from "node:path";
|
|
100825
100867
|
import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
100826
100868
|
|
|
100827
100869
|
// ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
|
|
@@ -106104,14 +106146,14 @@ function compactJsonResult(result, verbose) {
|
|
|
106104
106146
|
// src/project/runLog.ts
|
|
106105
106147
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
106106
106148
|
import { mkdir as mkdir33, writeFile as writeFile26 } from "node:fs/promises";
|
|
106107
|
-
import { dirname as dirname39, join as
|
|
106149
|
+
import { dirname as dirname39, join as join97 } from "node:path";
|
|
106108
106150
|
var createPhaseRunId = () => {
|
|
106109
106151
|
const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
|
|
106110
106152
|
return `run_${timestamp}_${randomUUID5().slice(0, 8)}`;
|
|
106111
106153
|
};
|
|
106112
106154
|
async function writePhaseRunLog(input) {
|
|
106113
|
-
const relPath =
|
|
106114
|
-
const absPath =
|
|
106155
|
+
const relPath = join97(".tmp", "context-runtime", "runs", `${input.runId}.json`);
|
|
106156
|
+
const absPath = join97(input.projectRoot, relPath);
|
|
106115
106157
|
await mkdir33(dirname39(absPath), { recursive: true });
|
|
106116
106158
|
await writeFile26(absPath, `${JSON.stringify({
|
|
106117
106159
|
run_id: input.runId,
|
|
@@ -107211,7 +107253,7 @@ init_reviewApplyIndexer();
|
|
|
107211
107253
|
init_approvedKnowledgeSnapshots();
|
|
107212
107254
|
import { existsSync as existsSync25 } from "node:fs";
|
|
107213
107255
|
import { readFile as readFile76 } from "node:fs/promises";
|
|
107214
|
-
import { join as
|
|
107256
|
+
import { join as join98 } from "node:path";
|
|
107215
107257
|
|
|
107216
107258
|
// src/project/reviewCandidateAuthority.ts
|
|
107217
107259
|
init_src2();
|
|
@@ -107274,7 +107316,7 @@ async function prepareApprovedPage(input) {
|
|
|
107274
107316
|
next: "Refresh the current production or article revision, then reopen Review before approval."
|
|
107275
107317
|
});
|
|
107276
107318
|
}
|
|
107277
|
-
const relPath =
|
|
107319
|
+
const relPath = join98("knowledge", input.record.path);
|
|
107278
107320
|
const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
|
|
107279
107321
|
const previousPath = input.record.approved_revision?.previous_path;
|
|
107280
107322
|
if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
|
|
@@ -107289,13 +107331,13 @@ async function prepareApprovedPage(input) {
|
|
|
107289
107331
|
next: "Resolve the approved page path migration explicitly before approving this candidate."
|
|
107290
107332
|
});
|
|
107291
107333
|
}
|
|
107292
|
-
const absPath =
|
|
107334
|
+
const absPath = join98(input.projectRoot, relPath);
|
|
107293
107335
|
const existing = existsSync25(absPath) ? await readFile76(absPath, "utf8") : undefined;
|
|
107294
107336
|
let previous3;
|
|
107295
107337
|
if (previousPath !== undefined) {
|
|
107296
107338
|
if (existing !== undefined || existingView?.relPath !== `knowledge/${previousPath}`)
|
|
107297
107339
|
throw new TypeError("Page move destination or original identity changed; refresh its revision.");
|
|
107298
|
-
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(
|
|
107340
|
+
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join98(input.projectRoot, "knowledge", previousPath), "utf8") };
|
|
107299
107341
|
}
|
|
107300
107342
|
if (input.record.approved_revision !== undefined) {
|
|
107301
107343
|
const base = previous3?.content ?? existing;
|
|
@@ -107342,7 +107384,7 @@ async function prepareApprovedPage(input) {
|
|
|
107342
107384
|
}
|
|
107343
107385
|
async function readProjectFileMaybe(projectRoot, relPath) {
|
|
107344
107386
|
try {
|
|
107345
|
-
return await readFile76(
|
|
107387
|
+
return await readFile76(join98(projectRoot, relPath), "utf8");
|
|
107346
107388
|
} catch (error) {
|
|
107347
107389
|
if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
107348
107390
|
return;
|
|
@@ -107565,7 +107607,7 @@ async function applyReviewDecisions(input) {
|
|
|
107565
107607
|
});
|
|
107566
107608
|
}
|
|
107567
107609
|
seenApprovedIds.set(approvedRef, row.candidate_id);
|
|
107568
|
-
const approvedPath =
|
|
107610
|
+
const approvedPath = join98("knowledge", row.path);
|
|
107569
107611
|
const previousPathCandidate = seenApprovedPaths.get(knowledgeTargetPathKey(approvedPath));
|
|
107570
107612
|
if (previousPathCandidate !== undefined) {
|
|
107571
107613
|
throw new ContextError(ExitCode.UserError, `multiple approved review decisions target the same knowledge path: ${approvedPath}`, {
|
|
@@ -107615,7 +107657,7 @@ async function applyReviewDecisions(input) {
|
|
|
107615
107657
|
for (const path3 of approvedPageIndex.byRelPath.keys()) {
|
|
107616
107658
|
if (pagesToWrite.some((page) => page.relPath === path3 || page.previous?.path === path3))
|
|
107617
107659
|
continue;
|
|
107618
|
-
const before = await readFile76(
|
|
107660
|
+
const before = await readFile76(join98(input.projectRoot, path3), "utf8");
|
|
107619
107661
|
const local = path3.replace(/^knowledge\//u, "");
|
|
107620
107662
|
const after = moveKnowledgeLinkTargets2(before, local, local, moved);
|
|
107621
107663
|
navigationTargets.push(reviewFileTarget({ path: path3, baseContent: before, targetContent: after }));
|
|
@@ -107699,12 +107741,12 @@ init_candidateLedger();
|
|
|
107699
107741
|
|
|
107700
107742
|
// src/project/localHtmlReport.ts
|
|
107701
107743
|
import { execFile as execFile11 } from "node:child_process";
|
|
107702
|
-
import { isAbsolute as isAbsolute17, join as
|
|
107744
|
+
import { isAbsolute as isAbsolute17, join as join99 } from "node:path";
|
|
107703
107745
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
107704
107746
|
import { promisify as promisify11 } from "node:util";
|
|
107705
107747
|
var execFileAsync5 = promisify11(execFile11);
|
|
107706
107748
|
function htmlReportReference(input) {
|
|
107707
|
-
const absolutePath = isAbsolute17(input.path) ? input.path :
|
|
107749
|
+
const absolutePath = isAbsolute17(input.path) ? input.path : join99(input.projectRoot, input.path);
|
|
107708
107750
|
return {
|
|
107709
107751
|
format: "html",
|
|
107710
107752
|
path: input.path,
|
|
@@ -108728,7 +108770,7 @@ init_maintenanceStorage();
|
|
|
108728
108770
|
init_productionFeedback();
|
|
108729
108771
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
108730
108772
|
import { readFile as readFile79 } from "node:fs/promises";
|
|
108731
|
-
import { join as
|
|
108773
|
+
import { join as join100 } from "node:path";
|
|
108732
108774
|
async function beginProductionRevision(input) {
|
|
108733
108775
|
return withProductionFeedback({ operation: "revision" }, () => withProjectWriteLock(input.projectRoot, "production-revision", async () => {
|
|
108734
108776
|
await recoverDurableMultiFileTransactions(input.projectRoot);
|
|
@@ -108767,7 +108809,7 @@ async function beginProductionRevision(input) {
|
|
|
108767
108809
|
const formal = approved.byPath.get(path3);
|
|
108768
108810
|
if (!prior && !formal)
|
|
108769
108811
|
throw invalid2("Write the current task first; there is no article draft to revise yet.");
|
|
108770
|
-
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot,
|
|
108812
|
+
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join100("knowledge", path3)), "utf8");
|
|
108771
108813
|
const sections = prior?.indexer_candidate.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
|
|
108772
108814
|
const sources = [];
|
|
108773
108815
|
for (const source2 of owner.sources) {
|
|
@@ -109407,7 +109449,7 @@ init_atomicWrite();
|
|
|
109407
109449
|
var import_yaml44 = __toESM(require_dist(), 1);
|
|
109408
109450
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
109409
109451
|
import { createHash as createHash31 } from "node:crypto";
|
|
109410
|
-
import { join as
|
|
109452
|
+
import { join as join104 } from "node:path";
|
|
109411
109453
|
var INLINE_LIMIT = 16 * 1024;
|
|
109412
109454
|
function record4(value) {
|
|
109413
109455
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
@@ -109433,8 +109475,8 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109433
109475
|
if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
|
|
109434
109476
|
return input.result;
|
|
109435
109477
|
const digest6 = createHash31("sha256").update(full).digest("hex");
|
|
109436
|
-
const root2 =
|
|
109437
|
-
const resultFile =
|
|
109478
|
+
const root2 = join104(input.projectRoot, ".tmp/context-runtime/action-results");
|
|
109479
|
+
const resultFile = join104(root2, `${digest6}.json`);
|
|
109438
109480
|
await atomicWriteFile(resultFile, full);
|
|
109439
109481
|
if (production)
|
|
109440
109482
|
return {
|
|
@@ -109445,7 +109487,7 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109445
109487
|
...pick(result, ["next", "next_preparation"])
|
|
109446
109488
|
};
|
|
109447
109489
|
const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
|
|
109448
|
-
const nextFile = next2 === undefined ? undefined :
|
|
109490
|
+
const nextFile = next2 === undefined ? undefined : join104(root2, `${digest6}.next.json`);
|
|
109449
109491
|
if (nextFile !== undefined)
|
|
109450
109492
|
await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
|
|
109451
109493
|
const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
|
|
@@ -109850,9 +109892,9 @@ function registerProjectActionCommands(program2) {
|
|
|
109850
109892
|
// src/commands/cleanClaudePluginCache.ts
|
|
109851
109893
|
init_cliFeedback();
|
|
109852
109894
|
import { existsSync as existsSync27 } from "node:fs";
|
|
109853
|
-
import { readdir as
|
|
109895
|
+
import { readdir as readdir27, rm as rm22 } from "node:fs/promises";
|
|
109854
109896
|
import { homedir } from "node:os";
|
|
109855
|
-
import { join as
|
|
109897
|
+
import { join as join105 } from "node:path";
|
|
109856
109898
|
var ORPHAN_MARKER = ".orphaned_at";
|
|
109857
109899
|
var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
|
|
109858
109900
|
var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
|
|
@@ -109865,40 +109907,40 @@ async function cleanClaudePluginCache(opts = {}) {
|
|
|
109865
109907
|
lines.push("· claude plugin cache: missing — nothing to clean");
|
|
109866
109908
|
return { lines, removed, scanned };
|
|
109867
109909
|
}
|
|
109868
|
-
const marketplaces = await
|
|
109910
|
+
const marketplaces = await readdir27(cacheRoot, { withFileTypes: true });
|
|
109869
109911
|
for (const mp of marketplaces) {
|
|
109870
109912
|
if (!mp.isDirectory())
|
|
109871
109913
|
continue;
|
|
109872
|
-
const mpDir =
|
|
109873
|
-
const plugins = await
|
|
109914
|
+
const mpDir = join105(cacheRoot, mp.name);
|
|
109915
|
+
const plugins = await readdir27(mpDir, { withFileTypes: true });
|
|
109874
109916
|
for (const pl of plugins) {
|
|
109875
109917
|
if (!pl.isDirectory())
|
|
109876
109918
|
continue;
|
|
109877
|
-
const plDir =
|
|
109878
|
-
const versions = await
|
|
109919
|
+
const plDir = join105(mpDir, pl.name);
|
|
109920
|
+
const versions = await readdir27(plDir, { withFileTypes: true });
|
|
109879
109921
|
for (const ver of versions) {
|
|
109880
109922
|
if (!ver.isDirectory())
|
|
109881
109923
|
continue;
|
|
109882
109924
|
scanned += 1;
|
|
109883
|
-
const verDir =
|
|
109884
|
-
const markerPath =
|
|
109925
|
+
const verDir = join105(plDir, ver.name);
|
|
109926
|
+
const markerPath = join105(verDir, ORPHAN_MARKER);
|
|
109885
109927
|
if (!existsSync27(markerPath))
|
|
109886
109928
|
continue;
|
|
109887
109929
|
const label2 = `${mp.name}/${pl.name}/${ver.name}`;
|
|
109888
109930
|
if (opts.dryRun) {
|
|
109889
109931
|
lines.push(` - would remove: ${label2}`);
|
|
109890
109932
|
} else {
|
|
109891
|
-
await
|
|
109933
|
+
await rm22(verDir, { recursive: true, force: true });
|
|
109892
109934
|
removed += 1;
|
|
109893
109935
|
lines.push(` ✓ removed: ${label2}`);
|
|
109894
109936
|
}
|
|
109895
109937
|
}
|
|
109896
109938
|
if (!opts.dryRun && await isEmptyDir(plDir)) {
|
|
109897
|
-
await
|
|
109939
|
+
await rm22(plDir, { recursive: true, force: true });
|
|
109898
109940
|
}
|
|
109899
109941
|
}
|
|
109900
109942
|
if (!opts.dryRun && await isEmptyDir(mpDir)) {
|
|
109901
|
-
await
|
|
109943
|
+
await rm22(mpDir, { recursive: true, force: true });
|
|
109902
109944
|
}
|
|
109903
109945
|
}
|
|
109904
109946
|
if (scanned === 0) {
|
|
@@ -109913,11 +109955,11 @@ function resolveClaudePluginCacheRoot(opts) {
|
|
|
109913
109955
|
if (explicitRoot)
|
|
109914
109956
|
return explicitRoot;
|
|
109915
109957
|
const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
|
|
109916
|
-
return
|
|
109958
|
+
return join105(home, ".claude", "plugins", "cache");
|
|
109917
109959
|
}
|
|
109918
109960
|
async function isEmptyDir(dir) {
|
|
109919
109961
|
try {
|
|
109920
|
-
const entries2 = await
|
|
109962
|
+
const entries2 = await readdir27(dir);
|
|
109921
109963
|
return entries2.length === 0;
|
|
109922
109964
|
} catch {
|
|
109923
109965
|
return false;
|
|
@@ -109945,13 +109987,13 @@ init_exitCode();
|
|
|
109945
109987
|
|
|
109946
109988
|
// src/lib/packageVersion.ts
|
|
109947
109989
|
import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
|
|
109948
|
-
import { dirname as dirname42, join as
|
|
109990
|
+
import { dirname as dirname42, join as join106 } from "node:path";
|
|
109949
109991
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
109950
109992
|
function readPackageVersion() {
|
|
109951
109993
|
try {
|
|
109952
109994
|
let dir = dirname42(fileURLToPath8(import.meta.url));
|
|
109953
109995
|
for (let depth = 0;depth < 8; depth += 1) {
|
|
109954
|
-
const packagePath =
|
|
109996
|
+
const packagePath = join106(dir, "package.json");
|
|
109955
109997
|
if (existsSync28(packagePath)) {
|
|
109956
109998
|
const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
|
|
109957
109999
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
@@ -109991,7 +110033,7 @@ init_repoSourceRegistry();
|
|
|
109991
110033
|
init_writeLock();
|
|
109992
110034
|
import { execFile as execFile12 } from "node:child_process";
|
|
109993
110035
|
import { existsSync as existsSync29 } from "node:fs";
|
|
109994
|
-
import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as
|
|
110036
|
+
import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as rm23, symlink as symlink4 } from "node:fs/promises";
|
|
109995
110037
|
import { basename as basename11, dirname as dirname43, isAbsolute as isAbsolute19, relative as relative26, resolve as resolve34 } from "node:path";
|
|
109996
110038
|
import { promisify as promisify12 } from "node:util";
|
|
109997
110039
|
var execFileAsync6 = promisify12(execFile12);
|
|
@@ -110181,14 +110223,14 @@ async function cloneCheckout(input) {
|
|
|
110181
110223
|
try {
|
|
110182
110224
|
await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
|
|
110183
110225
|
} catch {
|
|
110184
|
-
await
|
|
110226
|
+
await rm23(target, { recursive: true, force: true });
|
|
110185
110227
|
try {
|
|
110186
110228
|
await execFileAsync6("git", ["clone", "--no-checkout", "--depth=1", input.remote, target], {
|
|
110187
110229
|
encoding: "utf8",
|
|
110188
110230
|
maxBuffer: 4 * 1024 * 1024
|
|
110189
110231
|
});
|
|
110190
110232
|
} catch (error) {
|
|
110191
|
-
await
|
|
110233
|
+
await rm23(target, { recursive: true, force: true });
|
|
110192
110234
|
const detail = error !== null && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : error instanceof Error ? error.message : String(error);
|
|
110193
110235
|
throw new ContextError(ExitCode.ExternalToolError, `cannot clone registered repository: ${input.remote}`, {
|
|
110194
110236
|
category: ErrorCategory.ExternalToolFailed,
|
|
@@ -110213,7 +110255,7 @@ async function cloneCheckout(input) {
|
|
|
110213
110255
|
await verifyCheckout({ checkout: target, remote: input.remote, ref: input.ref, subpaths: input.subpaths });
|
|
110214
110256
|
return target;
|
|
110215
110257
|
} catch (error) {
|
|
110216
|
-
await
|
|
110258
|
+
await rm23(target, { recursive: true, force: true });
|
|
110217
110259
|
throw error;
|
|
110218
110260
|
}
|
|
110219
110261
|
}
|
|
@@ -110229,7 +110271,7 @@ async function bindLocalAlias(input) {
|
|
|
110229
110271
|
const actualReal = await realpath10(actual).catch(() => null);
|
|
110230
110272
|
if (actualReal !== null && actualReal === await realpath10(input.checkout))
|
|
110231
110273
|
return;
|
|
110232
|
-
await
|
|
110274
|
+
await rm23(alias);
|
|
110233
110275
|
} else {
|
|
110234
110276
|
const actual = await realpath10(alias);
|
|
110235
110277
|
if (actual === await realpath10(input.checkout))
|
|
@@ -110338,14 +110380,14 @@ init_src2();
|
|
|
110338
110380
|
init_documentCapture();
|
|
110339
110381
|
import { existsSync as existsSync30 } from "node:fs";
|
|
110340
110382
|
import { readFile as readFile86 } from "node:fs/promises";
|
|
110341
|
-
import { join as
|
|
110383
|
+
import { join as join108 } from "node:path";
|
|
110342
110384
|
|
|
110343
110385
|
// src/project/sourceCommandViews.ts
|
|
110344
110386
|
init_documentSiteDetection();
|
|
110345
110387
|
init_workspace();
|
|
110346
110388
|
init_documentBatchManifest();
|
|
110347
110389
|
import { readFile as readFile85 } from "node:fs/promises";
|
|
110348
|
-
import { join as
|
|
110390
|
+
import { join as join107 } from "node:path";
|
|
110349
110391
|
function repoSourceAgentView(source2) {
|
|
110350
110392
|
return {
|
|
110351
110393
|
id: source2.id ?? source2.name,
|
|
@@ -110406,7 +110448,7 @@ async function fileSourceAgentViewWithNextAction(input) {
|
|
|
110406
110448
|
};
|
|
110407
110449
|
}
|
|
110408
110450
|
function documentSourceManifestPath(source2) {
|
|
110409
|
-
return source2.snapshot?.manifest ??
|
|
110451
|
+
return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
|
|
110410
110452
|
}
|
|
110411
110453
|
async function fileSourceDocumentSiteHint(input) {
|
|
110412
110454
|
const detection = await detectDocumentSiteFiles({
|
|
@@ -110416,7 +110458,7 @@ async function fileSourceDocumentSiteHint(input) {
|
|
|
110416
110458
|
let snapshotConfigured = false;
|
|
110417
110459
|
const manifest = documentSourceManifestPath(input.source);
|
|
110418
110460
|
try {
|
|
110419
|
-
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(
|
|
110461
|
+
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join107(input.projectRoot, manifest), "utf8")), input.source.name);
|
|
110420
110462
|
snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
|
|
110421
110463
|
} catch {
|
|
110422
110464
|
snapshotConfigured = false;
|
|
@@ -110449,11 +110491,11 @@ async function larkSourceAgentViewWithNextAction(input) {
|
|
|
110449
110491
|
init_documentBatchManifest();
|
|
110450
110492
|
init_documentSnapshotFidelity();
|
|
110451
110493
|
function documentSourceManifestPath2(source2) {
|
|
110452
|
-
return source2.snapshot?.manifest ??
|
|
110494
|
+
return source2.snapshot?.manifest ?? join108(source2.materializedAt, "manifest.json");
|
|
110453
110495
|
}
|
|
110454
110496
|
async function documentSnapshotState(input) {
|
|
110455
110497
|
const manifest = documentSourceManifestPath2(input.source);
|
|
110456
|
-
const manifestPath =
|
|
110498
|
+
const manifestPath = join108(input.projectRoot, manifest);
|
|
110457
110499
|
if (!existsSync30(manifestPath)) {
|
|
110458
110500
|
return {
|
|
110459
110501
|
snapshotReady: false,
|
|
@@ -110532,7 +110574,7 @@ async function documentSnapshotState(input) {
|
|
|
110532
110574
|
const missing = [
|
|
110533
110575
|
...parsed.files.map((file) => file.path),
|
|
110534
110576
|
...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
|
|
110535
|
-
].find((path3) => !existsSync30(
|
|
110577
|
+
].find((path3) => !existsSync30(join108(input.projectRoot, input.source.materializedAt, path3)));
|
|
110536
110578
|
if (missing !== undefined) {
|
|
110537
110579
|
return {
|
|
110538
110580
|
snapshotReady: false,
|
|
@@ -110634,7 +110676,7 @@ init_exitCode();
|
|
|
110634
110676
|
var import_yaml47 = __toESM(require_dist(), 1);
|
|
110635
110677
|
import { createHash as createHash32 } from "node:crypto";
|
|
110636
110678
|
import { readFile as readFile87, realpath as realpath11 } from "node:fs/promises";
|
|
110637
|
-
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as
|
|
110679
|
+
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join109, relative as relative27, resolve as resolve35 } from "node:path";
|
|
110638
110680
|
init_writeLock();
|
|
110639
110681
|
var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
|
|
110640
110682
|
function isDateSourceNamespace(value) {
|
|
@@ -110730,7 +110772,7 @@ function assertSafeFileInclude(value) {
|
|
|
110730
110772
|
}
|
|
110731
110773
|
async function readRegistryDocument(projectRoot, registryPath2) {
|
|
110732
110774
|
try {
|
|
110733
|
-
const content3 = await readFile87(
|
|
110775
|
+
const content3 = await readFile87(join109(projectRoot, registryPath2), "utf8");
|
|
110734
110776
|
return content3.trim().length === 0 ? { sources: [] } : import_yaml47.default.parse(content3);
|
|
110735
110777
|
} catch (error) {
|
|
110736
110778
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -110848,7 +110890,7 @@ async function addFileSourceUnlocked(input) {
|
|
|
110848
110890
|
const record6 = entry2;
|
|
110849
110891
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110850
110892
|
}), nextEntry];
|
|
110851
|
-
await atomicWriteFile(
|
|
110893
|
+
await atomicWriteFile(join109(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110852
110894
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110853
110895
|
const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110854
110896
|
if (entry === undefined) {
|
|
@@ -110904,7 +110946,7 @@ async function addLarkSourceUnlocked(input) {
|
|
|
110904
110946
|
const record6 = entry2;
|
|
110905
110947
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110906
110948
|
}), nextEntry];
|
|
110907
|
-
await atomicWriteFile(
|
|
110949
|
+
await atomicWriteFile(join109(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110908
110950
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110909
110951
|
const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110910
110952
|
if (entry === undefined) {
|
|
@@ -111108,8 +111150,8 @@ init_writeLock();
|
|
|
111108
111150
|
var import_yaml48 = __toESM(require_dist(), 1);
|
|
111109
111151
|
import { existsSync as existsSync31 } from "node:fs";
|
|
111110
111152
|
import { createHash as createHash33 } from "node:crypto";
|
|
111111
|
-
import { readFile as readFile88, readdir as
|
|
111112
|
-
import { isAbsolute as isAbsolute21, join as
|
|
111153
|
+
import { readFile as readFile88, readdir as readdir28, rm as rm24 } from "node:fs/promises";
|
|
111154
|
+
import { isAbsolute as isAbsolute21, join as join110, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
|
|
111113
111155
|
function sourceIdentity(source2) {
|
|
111114
111156
|
if (source2.kind === "source.collection")
|
|
111115
111157
|
return;
|
|
@@ -111141,7 +111183,7 @@ function collectStrings(value, output) {
|
|
|
111141
111183
|
}
|
|
111142
111184
|
}
|
|
111143
111185
|
async function yamlReferences(input) {
|
|
111144
|
-
const absolutePath =
|
|
111186
|
+
const absolutePath = join110(input.projectRoot, input.path);
|
|
111145
111187
|
if (!existsSync31(absolutePath))
|
|
111146
111188
|
return false;
|
|
111147
111189
|
const parsed = import_yaml48.default.parse(await readFile88(absolutePath, "utf8"));
|
|
@@ -111270,7 +111312,7 @@ async function registryRemovalWrite(projectRoot, source2) {
|
|
|
111270
111312
|
const path3 = registryPath2(source2.type);
|
|
111271
111313
|
if (path3 === null)
|
|
111272
111314
|
return;
|
|
111273
|
-
const absolutePath =
|
|
111315
|
+
const absolutePath = join110(projectRoot, path3);
|
|
111274
111316
|
const document4 = existsSync31(absolutePath) ? import_yaml48.default.parse(await readFile88(absolutePath, "utf8")) : { sources: [] };
|
|
111275
111317
|
return {
|
|
111276
111318
|
path: absolutePath,
|
|
@@ -111289,7 +111331,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
|
|
|
111289
111331
|
return absolute;
|
|
111290
111332
|
}
|
|
111291
111333
|
function safeManagedManifestPath(projectRoot, source2) {
|
|
111292
|
-
const manifest = source2.manifest ??
|
|
111334
|
+
const manifest = source2.manifest ?? join110(source2.materializedAt, "manifest.json");
|
|
111293
111335
|
if (isAbsolute21(manifest))
|
|
111294
111336
|
throw unsafeOwnership(source2, manifest);
|
|
111295
111337
|
const absolute = resolve36(projectRoot, manifest);
|
|
@@ -111451,7 +111493,7 @@ function publicRemovalResult(plan, action) {
|
|
|
111451
111493
|
};
|
|
111452
111494
|
}
|
|
111453
111495
|
async function pruneExtractRuntime(projectRoot, source2) {
|
|
111454
|
-
const fingerprintPath =
|
|
111496
|
+
const fingerprintPath = join110(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
|
|
111455
111497
|
const removedPhaseIds = new Set;
|
|
111456
111498
|
if (existsSync31(fingerprintPath)) {
|
|
111457
111499
|
const parsed = JSON.parse(await readFile88(fingerprintPath, "utf8"));
|
|
@@ -111468,14 +111510,14 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111468
111510
|
await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
|
|
111469
111511
|
`);
|
|
111470
111512
|
}
|
|
111471
|
-
const phaseOwnershipPath =
|
|
111513
|
+
const phaseOwnershipPath = join110(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
|
|
111472
111514
|
if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
|
|
111473
111515
|
const parsed = JSON.parse(await readFile88(phaseOwnershipPath, "utf8"));
|
|
111474
111516
|
const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
|
|
111475
111517
|
await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
|
|
111476
111518
|
`);
|
|
111477
111519
|
}
|
|
111478
|
-
const symbolPath =
|
|
111520
|
+
const symbolPath = join110(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
|
|
111479
111521
|
if (existsSync31(symbolPath)) {
|
|
111480
111522
|
const parsed = JSON.parse(await readFile88(symbolPath, "utf8"));
|
|
111481
111523
|
const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
|
|
@@ -111483,12 +111525,12 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111483
111525
|
await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
|
|
111484
111526
|
`);
|
|
111485
111527
|
}
|
|
111486
|
-
const snapshotRoot =
|
|
111528
|
+
const snapshotRoot = join110(projectRoot, ".tmp/context-runtime/extract/candidates");
|
|
111487
111529
|
const visit4 = async (directory) => {
|
|
111488
111530
|
if (!existsSync31(directory))
|
|
111489
111531
|
return;
|
|
111490
|
-
for (const entry of await
|
|
111491
|
-
const path3 =
|
|
111532
|
+
for (const entry of await readdir28(directory, { withFileTypes: true })) {
|
|
111533
|
+
const path3 = join110(directory, entry.name);
|
|
111492
111534
|
if (entry.isDirectory()) {
|
|
111493
111535
|
await visit4(path3);
|
|
111494
111536
|
continue;
|
|
@@ -111499,7 +111541,7 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111499
111541
|
const parsed = JSON.parse(await readFile88(path3, "utf8"));
|
|
111500
111542
|
const refs = Array.isArray(parsed.source_refs) ? parsed.source_refs : [];
|
|
111501
111543
|
if (parsed.source === source2.name || refs.some((ref2) => typeof ref2 === "string" && stringReferencesSource(ref2, source2))) {
|
|
111502
|
-
await
|
|
111544
|
+
await rm24(path3, { force: true });
|
|
111503
111545
|
}
|
|
111504
111546
|
} catch {}
|
|
111505
111547
|
}
|
|
@@ -111538,7 +111580,7 @@ async function removeProjectSource(input) {
|
|
|
111538
111580
|
});
|
|
111539
111581
|
}
|
|
111540
111582
|
await applyAtomicFileBatch({
|
|
111541
|
-
transactionRoot:
|
|
111583
|
+
transactionRoot: join110(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
|
|
111542
111584
|
writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
|
|
111543
111585
|
removals: plan.absoluteRemovals
|
|
111544
111586
|
});
|
|
@@ -112180,8 +112222,8 @@ init_cliFeedback();
|
|
|
112180
112222
|
init_exitCode();
|
|
112181
112223
|
var import_yaml51 = __toESM(require_dist(), 1);
|
|
112182
112224
|
import { constants as constants6, existsSync as existsSync32 } from "node:fs";
|
|
112183
|
-
import { lstat as lstat13, open as open5, readdir as
|
|
112184
|
-
import { dirname as dirname44, join as
|
|
112225
|
+
import { lstat as lstat13, open as open5, readdir as readdir29 } from "node:fs/promises";
|
|
112226
|
+
import { dirname as dirname44, join as join112, resolve as resolve38 } from "node:path";
|
|
112185
112227
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
112186
112228
|
function bundledSkillRoot() {
|
|
112187
112229
|
const directory = dirname44(fileURLToPath9(import.meta.url));
|
|
@@ -112208,10 +112250,10 @@ async function listProductionSkills(root2) {
|
|
|
112208
112250
|
}
|
|
112209
112251
|
}
|
|
112210
112252
|
async function readProductionSkills(root2) {
|
|
112211
|
-
const entries2 = (await
|
|
112253
|
+
const entries2 = (await readdir29(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
112212
112254
|
const skills = [];
|
|
112213
112255
|
for (const directory of entries2) {
|
|
112214
|
-
const entry =
|
|
112256
|
+
const entry = join112(root2, directory.name, "SKILL.md");
|
|
112215
112257
|
if (!(await lstat13(entry)).isFile())
|
|
112216
112258
|
throw new TypeError(`Skill entry must be a regular file: ${entry}`);
|
|
112217
112259
|
const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
|
|
@@ -112619,8 +112661,8 @@ init_cliFeedback();
|
|
|
112619
112661
|
init_errors3();
|
|
112620
112662
|
init_exitCode();
|
|
112621
112663
|
import { createHash as createHash34 } from "node:crypto";
|
|
112622
|
-
import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as
|
|
112623
|
-
import { dirname as dirname46, join as
|
|
112664
|
+
import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir30, rename as rename9, rm as rm25, writeFile as writeFile28 } from "node:fs/promises";
|
|
112665
|
+
import { dirname as dirname46, join as join113, resolve as resolve40 } from "node:path";
|
|
112624
112666
|
var MARKER = ".context-skill-install.json";
|
|
112625
112667
|
function conflict(path3) {
|
|
112626
112668
|
throw new ContextError(ExitCode.UserError, `Local skill install conflict: ${path3}`, {
|
|
@@ -112648,10 +112690,10 @@ async function checkParents(path3) {
|
|
|
112648
112690
|
async function digest7(root2) {
|
|
112649
112691
|
const hash4 = createHash34("sha256");
|
|
112650
112692
|
async function visit4(dir, prefix) {
|
|
112651
|
-
for (const name3 of (await
|
|
112693
|
+
for (const name3 of (await readdir30(dir)).sort()) {
|
|
112652
112694
|
if (!prefix && name3 === MARKER)
|
|
112653
112695
|
continue;
|
|
112654
|
-
const path3 =
|
|
112696
|
+
const path3 = join113(dir, name3);
|
|
112655
112697
|
const entry = await lstat14(path3);
|
|
112656
112698
|
if (entry.isSymbolicLink())
|
|
112657
112699
|
conflict(path3);
|
|
@@ -112671,31 +112713,31 @@ async function installLocalSkills(root2, path3, dryRun, agent) {
|
|
|
112671
112713
|
if (!path3.trim())
|
|
112672
112714
|
conflict("--local requires a non-empty path");
|
|
112673
112715
|
const targetRoot = resolve40(path3);
|
|
112674
|
-
const skillsRoot =
|
|
112716
|
+
const skillsRoot = join113(targetRoot, "skills");
|
|
112675
112717
|
await checkParents(skillsRoot);
|
|
112676
|
-
const sourceRoot2 =
|
|
112718
|
+
const sourceRoot2 = join113(root2, "skills");
|
|
112677
112719
|
const commandPlans = [];
|
|
112678
112720
|
const commandEntries = new Set;
|
|
112679
112721
|
if (agent === "claude" || agent === "cursor") {
|
|
112680
|
-
for (const name3 of await
|
|
112722
|
+
for (const name3 of await readdir30(join113(root2, "claude", "commands"))) {
|
|
112681
112723
|
if (name3.endsWith(".md"))
|
|
112682
112724
|
commandEntries.add(name3.slice(0, -3));
|
|
112683
112725
|
}
|
|
112684
|
-
const commandsRoot =
|
|
112726
|
+
const commandsRoot = join113(targetRoot, "commands");
|
|
112685
112727
|
await checkParents(commandsRoot);
|
|
112686
|
-
for (const entry of await
|
|
112728
|
+
for (const entry of await readdir30(join113(root2, agent, "commands"), { withFileTypes: true })) {
|
|
112687
112729
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
112688
112730
|
continue;
|
|
112689
|
-
let content3 = await readFile94(
|
|
112731
|
+
let content3 = await readFile94(join113(root2, agent, "commands", entry.name), "utf8");
|
|
112690
112732
|
if (agent === "claude") {
|
|
112691
112733
|
const frontmatter2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112692
112734
|
if (!frontmatter2)
|
|
112693
|
-
conflict(
|
|
112735
|
+
conflict(join113(root2, agent, "commands", entry.name));
|
|
112694
112736
|
content3 = `${frontmatter2[1]}disable-model-invocation: true
|
|
112695
112737
|
${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmatter2[3]}${content3.slice(frontmatter2[0].length)}`;
|
|
112696
112738
|
}
|
|
112697
|
-
const target =
|
|
112698
|
-
const marker =
|
|
112739
|
+
const target = join113(commandsRoot, entry.name);
|
|
112740
|
+
const marker = join113(commandsRoot, `.context-${entry.name}.json`);
|
|
112699
112741
|
for (const file of [target, marker]) {
|
|
112700
112742
|
const existing = await stat11(file);
|
|
112701
112743
|
if (existing && (!existing.isFile() || existing.isSymbolicLink()))
|
|
@@ -112716,14 +112758,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112716
112758
|
commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
|
|
112717
112759
|
}
|
|
112718
112760
|
if (!commandPlans.length)
|
|
112719
|
-
conflict(
|
|
112761
|
+
conflict(join113(root2, agent, "commands"));
|
|
112720
112762
|
}
|
|
112721
112763
|
const plans = [];
|
|
112722
|
-
for (const entry of (await
|
|
112723
|
-
if (!entry.isDirectory() || !await stat11(
|
|
112764
|
+
for (const entry of (await readdir30(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
112765
|
+
if (!entry.isDirectory() || !await stat11(join113(sourceRoot2, entry.name, "SKILL.md")))
|
|
112724
112766
|
continue;
|
|
112725
|
-
const source2 =
|
|
112726
|
-
const target =
|
|
112767
|
+
const source2 = join113(sourceRoot2, entry.name);
|
|
112768
|
+
const target = join113(skillsRoot, entry.name);
|
|
112727
112769
|
if (commandEntries.has(entry.name)) {
|
|
112728
112770
|
if (await stat11(target))
|
|
112729
112771
|
conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
|
|
@@ -112733,7 +112775,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112733
112775
|
if (existing) {
|
|
112734
112776
|
if (!existing.isDirectory() || existing.isSymbolicLink())
|
|
112735
112777
|
conflict(target);
|
|
112736
|
-
const markerPath =
|
|
112778
|
+
const markerPath = join113(target, MARKER);
|
|
112737
112779
|
if (!(await stat11(markerPath))?.isFile())
|
|
112738
112780
|
conflict(target);
|
|
112739
112781
|
let marker;
|
|
@@ -112752,14 +112794,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112752
112794
|
if (!dryRun) {
|
|
112753
112795
|
await mkdir36(skillsRoot, { recursive: true });
|
|
112754
112796
|
for (const plan of plans) {
|
|
112755
|
-
const staging = await mkdtemp5(
|
|
112756
|
-
const candidate =
|
|
112757
|
-
const previous3 =
|
|
112797
|
+
const staging = await mkdtemp5(join113(skillsRoot, ".context-install-"));
|
|
112798
|
+
const candidate = join113(staging, "candidate");
|
|
112799
|
+
const previous3 = join113(staging, "previous");
|
|
112758
112800
|
let moved = false;
|
|
112759
112801
|
try {
|
|
112760
112802
|
await cp2(plan.source, candidate, { recursive: true });
|
|
112761
112803
|
if (agent === "claude") {
|
|
112762
|
-
const skillFile =
|
|
112804
|
+
const skillFile = join113(candidate, "SKILL.md");
|
|
112763
112805
|
const content3 = await readFile94(skillFile, "utf8");
|
|
112764
112806
|
const parts = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112765
112807
|
if (parts && /^\s*context-public-entry:\s*["']?false["']?\s*$/mu.test(parts[2])) {
|
|
@@ -112768,7 +112810,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112768
112810
|
${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
112769
112811
|
}
|
|
112770
112812
|
}
|
|
112771
|
-
await writeFile28(
|
|
112813
|
+
await writeFile28(join113(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
|
|
112772
112814
|
`);
|
|
112773
112815
|
if (plan.exists) {
|
|
112774
112816
|
await rename9(plan.target, previous3);
|
|
@@ -112781,7 +112823,7 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112781
112823
|
await rename9(previous3, plan.target);
|
|
112782
112824
|
throw error;
|
|
112783
112825
|
}
|
|
112784
|
-
await
|
|
112826
|
+
await rm25(staging, { recursive: true, force: true });
|
|
112785
112827
|
} catch (error) {
|
|
112786
112828
|
throw new ContextError(ExitCode.WorkspaceStateError, `Local skill installation failed: ${plan.target}`, {
|
|
112787
112829
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -112792,13 +112834,13 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112792
112834
|
}
|
|
112793
112835
|
for (const command3 of commandPlans) {
|
|
112794
112836
|
await mkdir36(dirname46(command3.target), { recursive: true });
|
|
112795
|
-
const staging = await mkdtemp5(
|
|
112796
|
-
await writeFile28(
|
|
112797
|
-
await writeFile28(
|
|
112837
|
+
const staging = await mkdtemp5(join113(dirname46(command3.target), ".context-install-"));
|
|
112838
|
+
await writeFile28(join113(staging, "command"), command3.content);
|
|
112839
|
+
await writeFile28(join113(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
|
|
112798
112840
|
`);
|
|
112799
|
-
await rename9(
|
|
112800
|
-
await rename9(
|
|
112801
|
-
await
|
|
112841
|
+
await rename9(join113(staging, "command"), command3.target);
|
|
112842
|
+
await rename9(join113(staging, "marker"), command3.marker);
|
|
112843
|
+
await rm25(staging, { recursive: true, force: true });
|
|
112802
112844
|
}
|
|
112803
112845
|
}
|
|
112804
112846
|
return formatFeedback({
|
|
@@ -112821,10 +112863,10 @@ init_cliFeedback();
|
|
|
112821
112863
|
init_errors3();
|
|
112822
112864
|
init_exitCode();
|
|
112823
112865
|
import { lstat as lstat15 } from "node:fs/promises";
|
|
112824
|
-
import { join as
|
|
112866
|
+
import { join as join114, resolve as resolve41 } from "node:path";
|
|
112825
112867
|
var HOST_DIRS = { claude: ".claude", cursor: ".cursor", codex: ".agents" };
|
|
112826
112868
|
async function detectLocalAgent(agent, repo) {
|
|
112827
|
-
const path3 =
|
|
112869
|
+
const path3 = join114(repo, HOST_DIRS[agent]);
|
|
112828
112870
|
try {
|
|
112829
112871
|
const entry = await lstat15(path3);
|
|
112830
112872
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
@@ -112849,7 +112891,7 @@ async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocal
|
|
|
112849
112891
|
if (selectedAgent ? selectedAgent === "all" || agent === selectedAgent : await detect(agent, repo))
|
|
112850
112892
|
agents.push(agent);
|
|
112851
112893
|
}
|
|
112852
|
-
const targets = agents.length ? agents.map((agent) => ({ agent, path:
|
|
112894
|
+
const targets = agents.length ? agents.map((agent) => ({ agent, path: join114(repo, HOST_DIRS[agent]) })) : [{ path: join114(repo, ".agents") }];
|
|
112853
112895
|
const previews = [];
|
|
112854
112896
|
for (const target of targets)
|
|
112855
112897
|
previews.push(await installLocalSkills(root2, target.path, true, target.agent));
|
|
@@ -112882,7 +112924,7 @@ init_cliFeedback();
|
|
|
112882
112924
|
init_errors3();
|
|
112883
112925
|
init_exitCode();
|
|
112884
112926
|
import { existsSync as existsSync35 } from "node:fs";
|
|
112885
|
-
import { dirname as dirname48, join as
|
|
112927
|
+
import { dirname as dirname48, join as join116, resolve as resolve42 } from "node:path";
|
|
112886
112928
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
112887
112929
|
|
|
112888
112930
|
// src/project/pluginInstallTargets.ts
|
|
@@ -112891,9 +112933,9 @@ init_errors3();
|
|
|
112891
112933
|
init_exitCode();
|
|
112892
112934
|
import { execFile as execFile13 } from "node:child_process";
|
|
112893
112935
|
import { existsSync as existsSync34 } from "node:fs";
|
|
112894
|
-
import { cp as cp3, mkdir as mkdir37, readdir as
|
|
112936
|
+
import { cp as cp3, mkdir as mkdir37, readdir as readdir31, readFile as readFile95, rename as rename10, rm as rm26, writeFile as writeFile29 } from "node:fs/promises";
|
|
112895
112937
|
import { homedir as homedir2 } from "node:os";
|
|
112896
|
-
import { dirname as dirname47, join as
|
|
112938
|
+
import { dirname as dirname47, join as join115 } from "node:path";
|
|
112897
112939
|
import { promisify as promisify13 } from "node:util";
|
|
112898
112940
|
var execFileAsync7 = promisify13(execFile13);
|
|
112899
112941
|
var MARKETPLACE_NAME = "c4a";
|
|
@@ -112947,23 +112989,23 @@ async function claudePluginInstalled(pluginId) {
|
|
|
112947
112989
|
}
|
|
112948
112990
|
}
|
|
112949
112991
|
function codexHome() {
|
|
112950
|
-
return process.env.CODEX_HOME?.trim() ||
|
|
112992
|
+
return process.env.CODEX_HOME?.trim() || join115(homedir2(), ".codex");
|
|
112951
112993
|
}
|
|
112952
112994
|
function claudePluginCacheRoot() {
|
|
112953
112995
|
const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
|
|
112954
112996
|
if (explicitRoot)
|
|
112955
112997
|
return explicitRoot;
|
|
112956
112998
|
const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
|
|
112957
|
-
return
|
|
112999
|
+
return join115(home, ".claude", "plugins", "cache");
|
|
112958
113000
|
}
|
|
112959
113001
|
function sharedSkillsRoot() {
|
|
112960
|
-
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() ||
|
|
113002
|
+
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".agents", "skills");
|
|
112961
113003
|
}
|
|
112962
113004
|
function claudeSkillsRoot() {
|
|
112963
|
-
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() ||
|
|
113005
|
+
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".claude", "skills");
|
|
112964
113006
|
}
|
|
112965
113007
|
function cursorPluginRoot() {
|
|
112966
|
-
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() ||
|
|
113008
|
+
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join115(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
|
|
112967
113009
|
}
|
|
112968
113010
|
function blockHeader(line) {
|
|
112969
113011
|
const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
|
|
@@ -113014,7 +113056,7 @@ function pruneLegacyCodexConfigContent(content3) {
|
|
|
113014
113056
|
`), removed };
|
|
113015
113057
|
}
|
|
113016
113058
|
async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
113017
|
-
const configPath =
|
|
113059
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
113018
113060
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113019
113061
|
if (!current2)
|
|
113020
113062
|
return;
|
|
@@ -113031,10 +113073,10 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
|
113031
113073
|
}
|
|
113032
113074
|
}
|
|
113033
113075
|
async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
|
|
113034
|
-
const cacheRoot =
|
|
113076
|
+
const cacheRoot = join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
|
|
113035
113077
|
if (!existsSync34(cacheRoot))
|
|
113036
113078
|
return;
|
|
113037
|
-
const versions = (await
|
|
113079
|
+
const versions = (await readdir31(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
|
|
113038
113080
|
if (versions.length === 0)
|
|
113039
113081
|
return;
|
|
113040
113082
|
steps.push({
|
|
@@ -113043,7 +113085,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
|
|
|
113043
113085
|
status: dryRun ? "planned" : "ran"
|
|
113044
113086
|
});
|
|
113045
113087
|
if (!dryRun)
|
|
113046
|
-
await Promise.all(versions.map((version3) =>
|
|
113088
|
+
await Promise.all(versions.map((version3) => rm26(join115(cacheRoot, version3), { recursive: true, force: true })));
|
|
113047
113089
|
}
|
|
113048
113090
|
async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
|
|
113049
113091
|
await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
|
|
@@ -113053,7 +113095,7 @@ async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
|
|
|
113053
113095
|
}
|
|
113054
113096
|
async function isEmptyDir2(dir) {
|
|
113055
113097
|
try {
|
|
113056
|
-
return (await
|
|
113098
|
+
return (await readdir31(dir)).length === 0;
|
|
113057
113099
|
} catch {
|
|
113058
113100
|
return false;
|
|
113059
113101
|
}
|
|
@@ -113063,31 +113105,31 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
|
|
|
113063
113105
|
if (!existsSync34(cacheRoot))
|
|
113064
113106
|
return;
|
|
113065
113107
|
const removed = [];
|
|
113066
|
-
const marketplaces = await
|
|
113108
|
+
const marketplaces = await readdir31(cacheRoot, { withFileTypes: true }).catch(() => []);
|
|
113067
113109
|
for (const marketplace of marketplaces) {
|
|
113068
113110
|
if (!marketplace.isDirectory())
|
|
113069
113111
|
continue;
|
|
113070
|
-
const pluginDir =
|
|
113112
|
+
const pluginDir = join115(cacheRoot, marketplace.name, PLUGIN_NAME);
|
|
113071
113113
|
if (!existsSync34(pluginDir))
|
|
113072
113114
|
continue;
|
|
113073
|
-
const versions = await
|
|
113115
|
+
const versions = await readdir31(pluginDir, { withFileTypes: true }).catch(() => []);
|
|
113074
113116
|
for (const version3 of versions) {
|
|
113075
113117
|
if (!version3.isDirectory())
|
|
113076
113118
|
continue;
|
|
113077
|
-
const versionDir =
|
|
113078
|
-
if (!existsSync34(
|
|
113119
|
+
const versionDir = join115(pluginDir, version3.name);
|
|
113120
|
+
if (!existsSync34(join115(versionDir, ORPHAN_MARKER2)))
|
|
113079
113121
|
continue;
|
|
113080
113122
|
removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
|
|
113081
113123
|
if (!dryRun) {
|
|
113082
|
-
await
|
|
113124
|
+
await rm26(versionDir, { recursive: true, force: true });
|
|
113083
113125
|
}
|
|
113084
113126
|
}
|
|
113085
113127
|
if (!dryRun && await isEmptyDir2(pluginDir)) {
|
|
113086
|
-
await
|
|
113128
|
+
await rm26(pluginDir, { recursive: true, force: true });
|
|
113087
113129
|
}
|
|
113088
|
-
const marketplaceDir =
|
|
113130
|
+
const marketplaceDir = join115(cacheRoot, marketplace.name);
|
|
113089
113131
|
if (!dryRun && await isEmptyDir2(marketplaceDir)) {
|
|
113090
|
-
await
|
|
113132
|
+
await rm26(marketplaceDir, { recursive: true, force: true });
|
|
113091
113133
|
}
|
|
113092
113134
|
}
|
|
113093
113135
|
if (removed.length > 0) {
|
|
@@ -113106,12 +113148,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
113106
113148
|
return;
|
|
113107
113149
|
const removed = [];
|
|
113108
113150
|
for (const pluginName of LEGACY_PLUGIN_NAMES) {
|
|
113109
|
-
const pluginDir =
|
|
113151
|
+
const pluginDir = join115(cacheRoot, MARKETPLACE_NAME, pluginName);
|
|
113110
113152
|
if (!existsSync34(pluginDir))
|
|
113111
113153
|
continue;
|
|
113112
113154
|
removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
|
|
113113
113155
|
if (!dryRun) {
|
|
113114
|
-
await
|
|
113156
|
+
await rm26(pluginDir, { recursive: true, force: true });
|
|
113115
113157
|
}
|
|
113116
113158
|
}
|
|
113117
113159
|
if (removed.length > 0) {
|
|
@@ -113123,12 +113165,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
113123
113165
|
}
|
|
113124
113166
|
}
|
|
113125
113167
|
async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
113126
|
-
const manifest = await readFile95(
|
|
113168
|
+
const manifest = await readFile95(join115(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
|
|
113127
113169
|
const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
|
|
113128
113170
|
if (!currentVersion)
|
|
113129
113171
|
return;
|
|
113130
|
-
const pluginDir =
|
|
113131
|
-
const staleVersions = (await
|
|
113172
|
+
const pluginDir = join115(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
|
|
113173
|
+
const staleVersions = (await readdir31(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
|
|
113132
113174
|
if (staleVersions.length === 0)
|
|
113133
113175
|
return;
|
|
113134
113176
|
steps.push({
|
|
@@ -113137,7 +113179,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
|
113137
113179
|
status: dryRun ? "planned" : "ran"
|
|
113138
113180
|
});
|
|
113139
113181
|
if (!dryRun) {
|
|
113140
|
-
await Promise.all(staleVersions.map((version3) =>
|
|
113182
|
+
await Promise.all(staleVersions.map((version3) => rm26(join115(pluginDir, version3), { recursive: true, force: true })));
|
|
113141
113183
|
}
|
|
113142
113184
|
}
|
|
113143
113185
|
function enableCodexPluginConfig(content3) {
|
|
@@ -113201,7 +113243,7 @@ source = ${JSON.stringify(root2)}
|
|
|
113201
113243
|
`;
|
|
113202
113244
|
}
|
|
113203
113245
|
async function ensureCodexPluginEnabled() {
|
|
113204
|
-
const configPath =
|
|
113246
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
113205
113247
|
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113206
113248
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113207
113249
|
const next2 = enableCodexPluginConfig(current2);
|
|
@@ -113210,7 +113252,7 @@ async function ensureCodexPluginEnabled() {
|
|
|
113210
113252
|
}
|
|
113211
113253
|
}
|
|
113212
113254
|
async function ensureCodexLocalMarketplace(root2) {
|
|
113213
|
-
const configPath =
|
|
113255
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
113214
113256
|
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113215
113257
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113216
113258
|
const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
|
|
@@ -113219,7 +113261,7 @@ async function ensureCodexLocalMarketplace(root2) {
|
|
|
113219
113261
|
}
|
|
113220
113262
|
}
|
|
113221
113263
|
async function codexPluginVersion(root2) {
|
|
113222
|
-
const manifestPath =
|
|
113264
|
+
const manifestPath = join115(root2, "codex", ".codex-plugin", "plugin.json");
|
|
113223
113265
|
const manifest = JSON.parse(await readFile95(manifestPath, "utf8"));
|
|
113224
113266
|
if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
|
|
113225
113267
|
throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
|
|
@@ -113227,13 +113269,13 @@ async function codexPluginVersion(root2) {
|
|
|
113227
113269
|
return manifest.version;
|
|
113228
113270
|
}
|
|
113229
113271
|
function codexPluginCacheDir(version3) {
|
|
113230
|
-
return
|
|
113272
|
+
return join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
|
|
113231
113273
|
}
|
|
113232
113274
|
async function replaceDirectoryFromSource(source2, target) {
|
|
113233
113275
|
await mkdir37(dirname47(target), { recursive: true });
|
|
113234
113276
|
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
113235
113277
|
const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
|
|
113236
|
-
await
|
|
113278
|
+
await rm26(temporary, { recursive: true, force: true });
|
|
113237
113279
|
await cp3(source2, temporary, { recursive: true, force: true });
|
|
113238
113280
|
const hadPrevious = existsSync34(target);
|
|
113239
113281
|
try {
|
|
@@ -113241,16 +113283,16 @@ async function replaceDirectoryFromSource(source2, target) {
|
|
|
113241
113283
|
await rename10(target, previous3);
|
|
113242
113284
|
await rename10(temporary, target);
|
|
113243
113285
|
if (hadPrevious)
|
|
113244
|
-
await
|
|
113286
|
+
await rm26(previous3, { recursive: true, force: true });
|
|
113245
113287
|
} catch (error) {
|
|
113246
|
-
await
|
|
113288
|
+
await rm26(temporary, { recursive: true, force: true });
|
|
113247
113289
|
if (hadPrevious && !existsSync34(target) && existsSync34(previous3))
|
|
113248
113290
|
await rename10(previous3, target);
|
|
113249
113291
|
throw error;
|
|
113250
113292
|
}
|
|
113251
113293
|
}
|
|
113252
113294
|
async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
113253
|
-
const source2 =
|
|
113295
|
+
const source2 = join115(root2, "codex");
|
|
113254
113296
|
const target = codexPluginCacheDir(version3);
|
|
113255
113297
|
steps.push({
|
|
113256
113298
|
agent: "codex",
|
|
@@ -113262,13 +113304,13 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
|
113262
113304
|
await replaceDirectoryFromSource(source2, target);
|
|
113263
113305
|
}
|
|
113264
113306
|
async function bundledProviderSkillNames(root2) {
|
|
113265
|
-
const skillsRoot =
|
|
113266
|
-
const entries2 = await
|
|
113307
|
+
const skillsRoot = join115(root2, "skills");
|
|
113308
|
+
const entries2 = await readdir31(skillsRoot, { withFileTypes: true });
|
|
113267
113309
|
const names = [];
|
|
113268
113310
|
for (const entry of entries2) {
|
|
113269
113311
|
if (!entry.isDirectory() || entry.name === "context")
|
|
113270
113312
|
continue;
|
|
113271
|
-
const skillPath =
|
|
113313
|
+
const skillPath = join115(skillsRoot, entry.name, "SKILL.md");
|
|
113272
113314
|
if (!existsSync34(skillPath))
|
|
113273
113315
|
continue;
|
|
113274
113316
|
const skill = await readFile95(skillPath, "utf8");
|
|
@@ -113283,10 +113325,10 @@ async function bundledProviderSkillNames(root2) {
|
|
|
113283
113325
|
return names;
|
|
113284
113326
|
}
|
|
113285
113327
|
async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
|
|
113286
|
-
const sourceRoot2 =
|
|
113328
|
+
const sourceRoot2 = join115(root2, "skills");
|
|
113287
113329
|
for (const name3 of await bundledProviderSkillNames(root2)) {
|
|
113288
|
-
const source2 =
|
|
113289
|
-
const target =
|
|
113330
|
+
const source2 = join115(sourceRoot2, name3);
|
|
113331
|
+
const target = join115(targetRoot, name3);
|
|
113290
113332
|
steps.push({
|
|
113291
113333
|
agent,
|
|
113292
113334
|
command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
|
|
@@ -113297,7 +113339,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
|
|
|
113297
113339
|
}
|
|
113298
113340
|
}
|
|
113299
113341
|
async function installCursor(root2, dryRun, steps) {
|
|
113300
|
-
const source2 =
|
|
113342
|
+
const source2 = join115(root2, "cursor");
|
|
113301
113343
|
const target = cursorPluginRoot();
|
|
113302
113344
|
steps.push({
|
|
113303
113345
|
agent: "cursor",
|
|
@@ -113352,12 +113394,12 @@ async function installCodex(root2, dryRun, steps) {
|
|
|
113352
113394
|
steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
|
|
113353
113395
|
steps.push({
|
|
113354
113396
|
agent: "codex",
|
|
113355
|
-
command: `ensure ${shellQuote8(
|
|
113397
|
+
command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
|
|
113356
113398
|
status: dryRun ? "planned" : "ran"
|
|
113357
113399
|
});
|
|
113358
113400
|
steps.push({
|
|
113359
113401
|
agent: "codex",
|
|
113360
|
-
command: `ensure ${shellQuote8(
|
|
113402
|
+
command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
|
|
113361
113403
|
status: dryRun ? "planned" : "ran"
|
|
113362
113404
|
});
|
|
113363
113405
|
if (dryRun) {
|
|
@@ -113412,13 +113454,13 @@ function pluginRootCandidates() {
|
|
|
113412
113454
|
return [resolve42(envRoot)];
|
|
113413
113455
|
const candidates = [];
|
|
113414
113456
|
for (const dir of packageCandidateDirs()) {
|
|
113415
|
-
candidates.push(
|
|
113416
|
-
candidates.push(
|
|
113457
|
+
candidates.push(join116(dir, "plugins"));
|
|
113458
|
+
candidates.push(join116(dir, "dist", "plugins"));
|
|
113417
113459
|
}
|
|
113418
113460
|
return [...new Set(candidates)];
|
|
113419
113461
|
}
|
|
113420
113462
|
function isInstallablePluginRoot(root2) {
|
|
113421
|
-
return existsSync35(
|
|
113463
|
+
return existsSync35(join116(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join116(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join116(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join116(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join116(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join116(root2, "skills"));
|
|
113422
113464
|
}
|
|
113423
113465
|
function resolveBundledPluginsRoot() {
|
|
113424
113466
|
const candidates = pluginRootCandidates();
|
|
@@ -113665,10 +113707,10 @@ function readQuickstartPath() {
|
|
|
113665
113707
|
try {
|
|
113666
113708
|
let dir = dirname49(fileURLToPath11(import.meta.url));
|
|
113667
113709
|
for (let i2 = 0;i2 < 8; i2++) {
|
|
113668
|
-
const candidate =
|
|
113710
|
+
const candidate = join117(dir, "docs", "quickstart.md");
|
|
113669
113711
|
if (existsSync36(candidate))
|
|
113670
113712
|
return candidate;
|
|
113671
|
-
const pkg =
|
|
113713
|
+
const pkg = join117(dir, "package.json");
|
|
113672
113714
|
if (existsSync36(pkg))
|
|
113673
113715
|
return candidate;
|
|
113674
113716
|
const parent = dirname49(dir);
|
|
@@ -113677,7 +113719,7 @@ function readQuickstartPath() {
|
|
|
113677
113719
|
dir = parent;
|
|
113678
113720
|
}
|
|
113679
113721
|
} catch {}
|
|
113680
|
-
return
|
|
113722
|
+
return join117(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
|
|
113681
113723
|
}
|
|
113682
113724
|
var GREEN = "\x1B[32m";
|
|
113683
113725
|
var RESET = "\x1B[0m";
|